#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>

#include <poll.h>

#define SERVPORT 3333 //定义端口号
#define BACKLOG 10 //请求队列中允许的最大请求数
#define MAXDATASIZE 50 //数据长度
#define INIT_SIZE 128

int main() {
    struct sockaddr_in server_sockaddr, client_sockaddr;
    int sin_size, recvbytes;
    int sockfd, client_fd; 
    char buf[MAXDATASIZE];
	
	int ready_number;
	
    if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("创建 server socket 失败");
        exit(1);
    }

    printf("Socket success!,sockfd=%d\n", sockfd);

    server_sockaddr.sin_family = AF_INET;
    server_sockaddr.sin_port = htons(SERVPORT);
    server_sockaddr.sin_addr.s_addr = INADDR_ANY;
	
    if((bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr))) == -1) {
        perror("bind");
        exit(-1);
    }

    printf("bind success!\n");
	
    if(listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    printf("listening ... \n");
	
	// 初始化pollfd数组，这个数组的第一个元素是listen_fd，
	// 其余的用来记录将要连接的connect_fd
	struct pollfd event_set[INIT_SIZE]; 
	event_set[0].fd = sockfd; 
	event_set[0].events = POLLRDNORM;
	
	// 用-1表示这个数组位置还没有被占用
	int i; 
	for (i = 1; i < INIT_SIZE; i++) { 
		event_set[i].fd = -1; 
	}	

	for (;;) {
        ready_number = poll(event_set, INIT_SIZE, -1);
		if (ready_number < 0)
            perror("poll()");
		
		if (event_set[0].revents & POLLRDNORM) {
    		if((client_fd = accept(sockfd, (struct sockaddr *) &client_sockaddr, &sin_size)) == -1) {
        		perror("accept");
        		exit(1);
    		}
			// 找到一个可以记录该连接套接字的位置
			for (i = 1; i < INIT_SIZE; i++) { 
				if (event_set[i].fd < 0) { 
					event_set[i].fd = client_fd; 
					event_set[i].events = POLLRDNORM; 
					printf("accept success! fd = %d\n", client_fd);
					break; 
				}
			}

			if (i == INIT_SIZE) { 
				perror("can not hold so many clients"); 
			} 
			
			if (--ready_number <= 0) continue;	
		}

		for (i = 1; i < INIT_SIZE; i++) {
			int socket_fd; 
			if ((socket_fd = event_set[i].fd) < 0) continue;
		
			if (event_set[i].revents & (POLLRDNORM | POLLERR)) {
    			if((recvbytes = read(socket_fd, buf, MAXDATASIZE)) == -1) {
        			perror("recv");
        			exit(1);
    			}
			
				// 收到数据大小为 0，说明收到的是 FIN 终止连接请求
				if (recvbytes == 0) {
					event_set[i].fd = -1;
					close(socket_fd);
					continue;
				}		
	
    			printf("received a connection : %s\n", buf);
				// 清空 buf
				memset(buf, 0x00, sizeof(buf));

				// 模拟处理延迟，睡 2 秒
				sleep(2);
		
				write(socket_fd, "hello server", 13);

				// 模拟处理延迟，睡 2 秒
				sleep(2);
				// write again
				write(socket_fd, "hello server2", 14);
				
				if (--ready_number <= 0) break;
			}
		}
	}
	// 7. 关闭服务端 server socket
    close(sockfd);

}
